using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Edge.Common.Services
{
    /// <summary>
    /// TODO use IoC framework (Spring.NET or CastleProject MikroKernel)
    /// </summary>
    public class Locator
    {
        public Locator()
        {
        }

        #region implementation

        internal class IfcTable
        {
            #region singletone

            private static IfcTable _instance;

            public static IfcTable Instance()
            {
                if (_instance == null)
                {
                    lock (typeof(IfcTable))
                    {
                        if (_instance == null)
                            _instance = new IfcTable();
                    }
                }

                return _instance;
            }

            protected IfcTable()
            {
            }

            #endregion

            private Hashtable _table = new Hashtable();

            // TODO thread safety
            public object GetService(Type type)
            {
                //				if(!_table.Contains(type))
                //					throw new ArgumentException("service does not exists for type "  + type);
                return _table[type];
            }

            // TODO thread safety
            public void AddService(Type type, object obj)
            {
                if (type == null)
                    throw new ArgumentException("type");

                if (obj == null)
                    throw new ArgumentException("obj");

                if (_table.Contains(type))
                    throw new ArgumentException("service already exists for type " + type);

                _table.Add(type, obj);

            }

            public void RemoveService(Type type)
            {
                if (type == null)
                    throw new ArgumentException("type");

                _table.Remove(type);
            }

            public void Reset()
            {
                _table.Clear();
            }
        }

        #endregion

        /// <summary>
        /// return service from locator
        /// </summary>
        /// <param name="type">interface or class type</param>
        /// <returns></returns>
        public static object GetService(Type type)
        {
            return IfcTable.Instance().GetService(type);
        }

        /// <summary>
        /// return service from locator
        /// </summary>
        /// <typeparam name="T">interface or class type</typeparam>
        /// <returns></returns>
        public static T GetService<T>()
        {
            return (T)GetService(typeof(T));
        }

        /// <summary>
        /// add service to locator
        /// </summary>
        /// <param name="type">interface or class type</param>
        /// <param name="obj">service object</param>
        public static void AddService(Type type, object obj)
        {
            IfcTable.Instance().AddService(type, obj);
        }

        /// <summary>
        /// add service to locator
        /// </summary>
        /// <typeparam name="T">interface or class type</typeparam>
        /// <param name="obj">service object</param>
        public static void AddService<T>(T obj)
        {
            AddService(typeof(T), obj);
        }

        /// <summary>
        /// remove service from locator
        /// </summary>
        /// <param name="type">interface or class type</param>
        public static void RemoveService(Type type)
        {
            IfcTable.Instance().RemoveService(type);
        }

        /// <summary>
        /// remove all servoves from locator
        /// only for tests
        /// </summary>
        public static void Reset()
        {
            IfcTable.Instance().Reset();
        }
    }
}
